<template>
  <div class="json" :class="{root: isRoot}">
    <div class="title">
      <label v-if="title">{{ title }}</label>
    </div>
    <div class="row" :class="row.isList ? 'row-list' : ''" v-if="row">

      <el-button v-if="row?.items?.length" text
                 :icon="$data.expand ? CaretRight: CaretBottom "
                 class="expand"
                 @click="$data.expand = !$data.expand"></el-button>
      <el-input placeholder="属性" class="key" chk="*" v-model="row.key" :disabled="isRoot"></el-input>

      <el-input v-model="row.remark" placeholder="备注" class="remark"></el-input>

      <selector style="margin-left:4px;width:100px;" :readOnly="fixObject" v-model="row.type" :class="'st-' + row.type" chk="*"
                :data="parameterTypes"
                fields="name,remark" @change="type_change"></selector>

      <div class="multi" :style="{visibility: fixObject ? 'hidden': 'visible'}">
        <el-switch v-model="row.isList"></el-switch>
        <label :style="{visibility:row.isList?'visible':'hidden'}">数组</label>
      </div>
      <div class="rbtn">
        <el-button :style="{visibility:(row.type == 'Object') ?'visible':'hidden'}" text
                   @click="add_sub_click(row)"
                   :icon="CirclePlus"
                   title="添加子元素"></el-button>
        <el-button text
                   @click="$data.dlg_show=true"
                   :icon="Setting"
                   title="设置"></el-button>
        <el-button :style="{visibility: !isRoot ?'visible':'hidden'}" text
                   @click="add_click(row)"
                   :icon="Plus" title="添加同级元素"></el-button>
        <el-button :style="{visibility:!isRoot?'visible':'hidden'}"
                   text
                   @click="remove_click(row)"
                   :icon="Remove"></el-button>
      </div>

    </div>


    <template v-if="row && row.enumData && row.enumData.length">
      <div v-html="row.enumData.join(',')" style="margin-left:16px;margin-top:-8px;font-size:small;color:dimgray"></div>
    </template>


    <el-dialog title="详情" v-model="$data.dlg_show" width="66vw">
      <div class="card" v-if="row">
        <kv label="属性">
          <el-input placeholder="属性" class="key" chk="*" v-model="row.key" :disabled="isRoot"></el-input>
        </kv>
        <kv label="备注">
          <el-input v-model="row.remark" placeholder="备注" class="remark"></el-input>
        </kv>


        <kv label="类型">
          <selector v-model="row.type" class="type" chk="*" :data="parameterTypes"
                    fields="name,remark" @change="type_change"></selector>
        </kv>

        <kv label="是否数组">
          <div class="multi">
            <el-switch v-model="row.isList"></el-switch>
            <label :style="{visibility:row.isList?'visible':'hidden'}">数组</label></div>
        </kv>

        <kv label="文本格式" v-if="row.type == 'Text'">
          <selector v-model="row.stringType" enum="ApiParameterStringTypeEnum"
                    class="stringType" chk="*"></selector>
        </kv>

        <template v-if="row.type == 'Enum'">
          <kv label="可选值">
            <el-input placeholder="逗号分隔的枚举值" type="textarea"
                      v-model="row.enumData" class="enumData"></el-input>
          </kv>

          <!--                    <kv label="枚举类型">-->
          <!--                        <selector v-model="row.enumType" url="/dev/api-enum/list"></selector>-->
          <!--                    </kv>-->
        </template>

        <template v-else-if="row.type == 'Object'">
          <kv label="引用模型">
            <el-input v-model="row.objectApiModelType" placeholder="引用apiModel"
                      class="objectApiModelType"></el-input>

          </kv>

          <kv label="从Json中添加">
            <el-input v-model="$data.jsonDefine" placeholder="从Json中添加" type="textarea"></el-input>
            <el-button style="width: 60px; padding: 6px; font-size: 14px;" @click="json_define_click">添加
            </el-button>
          </kv>
        </template>


        <template v-else-if="row.type != 'File'">
          <kv label="默认值">
            <el-input v-model="row.defaultValue" placeholder="默认值"
                      class="defaultValue"></el-input>
          </kv>
          <kv label="是否必填">
            <div class="required">
              <el-switch v-model="row.required"></el-switch>
              <label :style="{visibility:row.required?'visible':'hidden'}">必填</label>
            </div>
          </kv>
        </template>
        <kv style="visibility: hidden"></kv>
      </div>

      <el-button style="display: flex;margin: 20px auto;width: 80px; padding: 8px; font-size: 14px;"
                 type="primary" @click="$data.dlg_show=false">确定
      </el-button>
    </el-dialog>

    <div class="sub" v-if="!$data.expand && row?.items">
      <api-json v-for="(item,index) in row.items" :key="index"
                v-model="row.items[index]" :parent="row"></api-json>
    </div>
  </div>
</template>
<script setup>
import '../styles/cmn.scss'
/**
 * Created by CodeGenerator  at 2022-09-07 13:54:56
 */
import apiJson from "./api-json-parameter.vue"
import {Setting, CirclePlus, Plus, Remove, CaretBottom, CaretTop, CaretRight} from '@element-plus/icons-vue'


defineOptions({
  name: "api-json",
  inheritAttrs: true,
});

//定义 vue2的this,当前组件
const $self = getCurrentInstance();

//定义 $attrs
const $attrs = useAttrs();


//定义data
const $data = reactive({
  expand: false,
  jsonDefine: "",
  dlg_show: false
});


//定义属性
const $props = defineProps({
  title: {
    type: String, default() {
      return "";
    }
  },
  parent: {
    type: Object, default() {
      return null;
    }
  },
  fixObject: {
    type: Boolean, default() {
      return false;
    }
  }
});

const $model = defineModel({type: Object});

const list = ref();

//定义事件
const $emit = defineEmits(["update:modelValue", "loaded"]);

const row = $computed({
  get() {
    var value = $model.value;
    var ret = Object.assign({}, value);
    if (isRoot) {
      ret.key = ret.key || "根";
      ret.type = ret.type || "Object";
    }
    if ($props.fixObject) {
      ret.type = "Object";
    }
    if (!ret.items) {
      ret.items = [];
    }
    if (!jv.dataEquals(ret, value)) {
      $data.row = ret;
    }
    return value;
  }, set(v) {
    $emit("update:modelValue", Object.assign({}, v));
  }
});
const parameterTypes = $computed(function () {
  return jv.enum.ApiParameterTypeEnum.getData();
});
const isRoot = $computed(function () {
  return $props.parent == null;
});

const procJson = function (json) {
  var ret = [];
  Object.keys(json).forEach(key => {
    var value = json[key];
    var type = "Text";
    var items = [];
    if (jv.isNull(value)) {
      return;
    } else {
      var type2 = value.getJsType();
      if (type2 == "boolean") {
        type = "Boolean"
      } else if (type2 == "number") {
        type = "Int"
      } else if (type2 == "object") {
        type = "Object";
        items = procJson(value);
      }
    }
    ret.push({key, type, items});
  })
  return ret;
};
const json_define_click = function () {
  var json = JSON.parse($data.jsonDefine);
  procJson(json).forEach(it => {
    if (it.key in $data.row.items) {
      return;
    }
    $data.row.items.push(it);
  });
};
const type_change = function (v, m) {
  if (v != "Object") {
    if (!m.row) {
      m.row = {};
    }

    m.row.items = [];
  }
};
const expend_click = function (e) {
//当前是展开状态
  let button = e.target;
  let sub = button.closest(".row").nextElementSibling;
  let isShow = button.classList.contains("el-icon-caret-right")
  if (isShow) {
    button.classList.remove("el-icon-caret-right");
    button.classList.add("el-icon-caret-bottom");
    sub.style.display = "block";
  }
//当前是收起状态
  else {
    button.classList.add("el-icon-caret-right");
    button.classList.remove("el-icon-caret-bottom");
    sub.style.display = "none";
  }
};
const add_click = function (row) {
  var index = $props.parent.items.indexOf(row);
  var def = {items: [], type: row.type, stringType: "Normal"};
  $props.parent.items.insertAt(index, def);
};
const add_sub_click = function (row) {
  var last = row.items.getLast();
  var def = {items: [], type: "Text", stringType: "Normal"};
  if (last) {
    def.type = last.type;
  }
  row.items.push(def);
};
const remove_click = function (row) {
  if (!$props.parent) {
    return;
  }
  $props.parent.items.removeItem(row);
};


onMounted(() => {

})

</script>

<style lang="scss">

.st-Enum * {
  color: blue;
}

.st-Boolean * {
  color: blue;
}

.st-File * {
  color: orangered;
}
</style>